package ch.sfug.player{

	

	import ch.sfug.events.PlayerEvent;
	import ch.sfug.events.PlaylistEvent;
	import ch.sfug.net.loader.AbstractLoader;
	import ch.sfug.player.IExternalPlayer;
	import ch.sfug.player.IMediaPlayer;
	import ch.sfug.player.IPlaylist;
	import ch.sfug.player.IPlaylistNavigator;
	import flash.display.InteractiveObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;


	/**
	* dispatched when the player goto next track
	*/
	[Event(name="PlaylistEvent.NEXT",type="ch.sfug.events.PlaylistEvent")]
	/**
	* dispatched when next track is played
	*/
	[Event(name="PlaylistEvent.PREV",type="ch.sfug.events.PlaylistEvent")]
	/**
	* dispatched when an goto happend
	*/
	[Event(name="PlaylistEvent.GOTO",type="ch.sfug.events.PlaylistEvent")]
	/**
	* dispached when the navigator reach the end of the playlist
	*/
	[Event(name="PlaylistEvent.ENDLIST",type="ch.sfug.events.PlaylistEvent")]


	/**
	* a player for playlist playing
	* 
	* forwards hosted events
	*/
	public class PlaylistPlayer extends EventDispatcher implements IPlaylistNavigator,IMediaPlayer,IExternalPlayer {
		//{ ATTRIBUTES
		
		private var _playlist:IPlaylist=new Playlist();
		private var _loader:AbstractLoader;
		
		private var _currentPos:int = -1;
		
		private var _player:IMediaPlayer;
		
		private var _blockEnd:Boolean=false;

		
		//}

		//{ GETTER-SETTER
		
		/**
		* current playlist
		*/
		public function get playlist():IPlaylist{ return this._playlist; }
 		/** @private */
		public function set playlist(newValue:IPlaylist):void{
			this._playlist = newValue;
			firePLAYLIST_CHANGED(newValue);
		}
		
		

		public function get loader():AbstractLoader { return IExternalPlayer(_player).loader; }
 		/** @private */
		public function set loader(newValue:AbstractLoader):void{
			//IExternalPlayer(_player).loader = newValue;
		}
		public function get soundTransform():SoundTransform {
			return _player.soundTransform;
		}
		public function set soundTransform( st:SoundTransform ):void {
			_player.soundTransform = st;
		}
		//}


		//{ INIT
		public function PlaylistPlayer(pl:IMediaPlayer) {
			super();
			_player = pl;
			_player.addEventListener(PlayerEvent.END,handleEvent);
		}

		//}

		//{ METHODS
		
		
		/**
		* goto next
		*/
		public function next():void {
			if (hasNext())
			{
				stopOld();
				playPos(_currentPos + 1);
				fireNEXT(_currentPos, _playlist);
			}
		}
		/**
		* goto previews
		*/
		public function prev():void{
			if (hasPrev())
			{
				stopOld();
				
				playPos(_currentPos - 1);
				firePREV(_currentPos, _playlist);
			}
		}
		/**
		* has a next element
		* @return	
		*/
		public function hasNext():Boolean{
			return _playlist.numTrack > (_currentPos+1);
		}
		/**
		* has a previews element
		* @return	
		*/
		public function hasPrev():Boolean{
			return 0 < _currentPos;
		}
		/**
		* goto a specified track in playlist
		* @param	n	playlist position
		*/
		public function goto(n:int):void{
			if (0 <= n && n < _playlist.numTrack)
			{
				stopOld();
				
				playPos(n);
				fireGOTO(_currentPos, _playlist);
			}
		}
		/**
		* start play
		*/
		public function play():void {
			if (_currentPos < 0 && hasNext())
			{
				next();
			}
			else
				_player.play();
		}
		/**
		* pause player
		*/
		public function pause():void{
			_player.pause();
		}
		/**
		* stops the player
		*/
		public function stop():void{
			_player.stop();
		}
		/**
		 * end the player
		 */
		public function end():void {
			_player.end();
		}
		/**
		* seek to specified time
		* @param	time	ms to play
		*/
		public function seek(time:Number):void{
			_player.seek(time);
		}
		/**
		* checks if the player is playing
		* @return	
		*/
		public function isPlaying():Boolean{
			return _player.isPlaying();
		}
		/**
		* checks if the player is paused
		* @return	
		*/
		public function isPaused():Boolean{
			return _player.isPaused();
		}
		/**
		* checks if the player is stopped
		* @return	
		*/
		public function isStopped():Boolean{
			return _player.isStopped();
		}
		/**
		* checks if the palyer ist at end
		* @return	
		*/
		public function isAtEnd():Boolean{
			return _player.isAtEnd();
		}
		/**
		* 
		* @param	url	
		*/
		public function load(url:URLRequest):void{
			IExternalPlayer(_player).load(url);
		}
		
		
		
		
		override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
			super.addEventListener(type, listener, useCapture, priority, useWeakReference);
			_player.addEventListener(type, listener, useCapture, priority, useWeakReference);
		}
		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
			super.removeEventListener(type, listener, useCapture);
			_player.removeEventListener(type, listener, useCapture);
		}
		
		public function addLoaderListener(type:String, func:Function):void
		{
			IExternalPlayer(_player).addLoaderListener(type, func);
		}
		public function removeLoaderListener(type:String, func:Function):void
		{
			IExternalPlayer(_player).addLoaderListener(type, func);
		}
		public function get time():Number {
			if (_player != null)
				return _player.time;
			return 0;
		}
		
		public function get duration():Number{
			if (_player != null)
				return _player.duration;
			return 0;
		}
		//}

		//{ PRIVATE METHODS
		protected function handleEvent(e:Event):void
		{
			if (e.type == PlayerEvent.END && !_blockEnd)
			{
				if (hasNext())
				{
					next();
					return;
				}
				
			}
			
			
			dispatchEvent(e);
			
		}
		protected function playPos(n:int):void
		{
			_currentPos = n;
			IExternalPlayer(_player).load(_playlist.getTrack(n).location);
			play();
		}
		protected function stopOld():void
		{
			_blockEnd = true;
			_player.end();
			_blockEnd = false;
		}
		
		
		protected function fireNEXT(position:int,playlist:IPlaylist):void
		{
			dispatchEvent(new PlaylistEvent(PlaylistEvent.NEXT,position,playlist));
		}

		protected function firePREV(position:int,playlist:IPlaylist):void
		{
			dispatchEvent(new PlaylistEvent(PlaylistEvent.PREV,position,playlist));
		}

		protected function fireGOTO(position:int,playlist:IPlaylist):void
		{
			dispatchEvent(new PlaylistEvent(PlaylistEvent.GOTO,position,playlist));
		}

		protected function fireENDLIST(position:int,playlist:IPlaylist):void
		{
			dispatchEvent(new PlaylistEvent(PlaylistEvent.ENDLIST,position,playlist));
		}
		private function firePLAYLIST_CHANGED(playlist:IPlaylist):void{
			dispatchEvent(new PlaylistEvent(PlaylistEvent.PLAYLIST_CHANGED,0,playlist));
		}

		//}



	}

}

